﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SiGeSIB.Data.Providers;
using SiGeSIB.Data.Security;
using System.Data.SqlClient;
using System.Data;
using SiGeSIB.Data.Common;

namespace SiGeSIB.Data.Specialized.Providers
{
	public class SecurityDataProvider : BaseDataProvider, ISecurityDataProvider
	{
		#region ISecurityDataProvider Members

		#region Gets
		public User GetUser(string login)
		{
			User user = null;
			using (SqlConnection conn = _ConfigMgr.CreateConnection())
			{
				List<User> users = _GetUsers(conn, null, login);

				if (users != null && users.Count == 1)
					user = users[0];
			}
			return user;
		}

		public List<User> GetUsers(int[] ids)
		{
			using (SqlConnection conn = _ConfigMgr.CreateConnection())
			{
				return _GetUsers(conn, ids, null);
			}
		}

		internal List<User> _GetUsers(SqlConnection conn, int[] ids, string login)
		{
			using (SqlCommand cmd = conn.CreateCommand())
			{
				cmd.CommandType = CommandType.StoredProcedure;
				cmd.CommandText = "GetUsuarios";

				if (!string.IsNullOrEmpty(login))
					cmd.AddParameterWithValues("Login", login);
				else if (ids != null)
					cmd.AddParameterWithValues("Ids", ids.GetStringIds());

				cmd.AddParameterWithValues("Sep", SqlExtensions.CARRIAGE_RETURN);

				using (SqlDataReader dr = cmd.ExecuteReader())
				{
					if (dr.HasRows)
						return _ReadUsers(dr);
					else
						return null;
				}
			}
		}

		private List<User> _ReadUsers(SqlDataReader dr)
		{
			List<User> users = new List<User>();

			int IDX_Id = dr.GetOrdinal("Id");
			int IDX_Nome = dr.GetOrdinal("Nome");
			int IDX_Login = dr.GetOrdinal("Login");
			int IDX_Senha = dr.GetOrdinal("Senha");
			int IDX_Email = dr.GetOrdinal("Email");
			int IDX_IdPermissao = dr.GetOrdinal("IdPermissao");
			int IDX_Admin = dr.GetOrdinal("Admin");

			while (dr.Read())
			{
				int id = dr.GetInt32(IDX_Id);
				string name = dr.GetString(IDX_Nome);
				string login = dr.GetString(IDX_Login);
				string password = dr.GetString(IDX_Senha);
				string email = dr.GetString(IDX_Email);
				bool isAdmin = dr.GetBoolean(IDX_Admin);
				EPermissions permission = dr.GetEnum<EPermissions>(IDX_IdPermissao);

				User user = new User(isAdmin) { Name = name, Email = email, Id = id, Login = login, Password = password, Permissions = permission };

				users.Add(user);
			}

			return users;
		}
		#endregion

		public int InsertUser(User user)
		{
			using (SqlConnection conn = _ConfigMgr.CreateConnection())
				using (SqlCommand cmd = conn.CreateCommand())
				{
					cmd.CommandType = CommandType.StoredProcedure;
					cmd.CommandText = "InserirUsuario";

					cmd.AddParameterWithValues("Nome", user.Name);
					cmd.AddParameterWithValues("Login", user.Login);
					cmd.AddParameterWithValues("Senha", user.Password);
					cmd.AddParameterWithValues("Email", user.Email);
					cmd.AddParameterWithValues("IdPermissao", (int)user.Permissions);

					try
					{
						return cmd.ExecuteWithReturnValue();
					}
					catch (SqlException e)
					{
						if (e.Message.Contains("LOGINALREADYEXISTS"))
							throw new ValidationError("InvalidLogin", "Já existe usuário com o login informado.");
						else
							throw e;
					}
				}
		}

		public void UpdateUser(User user)
		{
			using (SqlConnection conn = _ConfigMgr.CreateConnection())
			using (SqlCommand cmd = conn.CreateCommand())
			{
				cmd.CommandType = CommandType.StoredProcedure;
				cmd.CommandText = "AtualizarUsuario";

				cmd.AddParameterWithValues("Id", user.Id);
				cmd.AddParameterWithValues("Nome", user.Name);
				cmd.AddParameterWithValues("Login", user.Login);
				cmd.AddParameterWithValues("Senha", user.Password);
				cmd.AddParameterWithValues("Email", user.Email);
				cmd.AddParameterWithValues("IdPermissao", (int)user.Permissions);

				try
				{
					cmd.ExecuteNonQuery();
				}
				catch (SqlException e)
				{
					if (e.Message.Contains("LOGINALREADYEXISTS"))
						throw new ValidationError("InvalidLogin", "Já existe usuário com o login informado.");
					else
						throw e;
				}
			}
		}

		public void RemoveUser(int id)
		{
			using(SqlConnection conn = _ConfigMgr.CreateConnection())
			using (SqlCommand cmd = conn.CreateCommand())
			{
				cmd.CommandType = CommandType.StoredProcedure;
				cmd.CommandText = "RemoverUsuario";
				cmd.AddParameterWithValues("Id", id);

				cmd.ExecuteNonQuery();
			}
		}

		public void SaveUserPermission(int userId, EPermissions permission)
		{
			using (SqlConnection conn = _ConfigMgr.CreateConnection())
				using (SqlCommand cmd = conn.CreateCommand())
				{
					cmd.CommandType = CommandType.StoredProcedure;
					cmd.CommandText = "AtualizarPermissaoUsuario";
					cmd.AddParameterWithValues("IdUsuario", userId);
					cmd.AddParameterWithValues("IdPermissao", (int)permission);

					cmd.ExecuteNonQuery();
				}
		}

		public EPermissions GetUserPermission(int userId)
		{
			using (SqlConnection conn = _ConfigMgr.CreateConnection())
			using (SqlCommand cmd = conn.CreateCommand())
			{
				cmd.CommandType = CommandType.StoredProcedure;
				cmd.CommandText = "GetPermissaoUsuario";
				cmd.AddParameterWithValues("IdUsuario", userId);

				return (EPermissions)cmd.ExecuteWithReturnValue();
			}
		}

		#endregion
	}
}
